/* Mesh.cpp  -- mesh representation 

Copyright (C) 2010 Gabriel Alises Cano, Javier Angulo Lucerón

This file is part of Computer Graphics : Final Project 09-10.

Computer Graphics : Final Project 09-10 is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Computer Graphics : Final Project 09-10 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Computer Graphics : Final Project 09-10.  If not, see <http://www.gnu.org/licenses/>. */

#include "Mesh.h"

Mesh::Mesh () {}

Mesh::Mesh (Mesh &m)
{
	triangs = m.get_triangs ();
	verts = m.get_verts ();
}

Mesh::~Mesh ()
{
	for (vector<Triangle *>::iterator it = triangs.begin (); it != triangs.end (); it++)
		delete *it;
}

vector<Triangle *> 
Mesh::get_face (Triangle * t)
{
	/* Candidates to be in the same face */
	vector<Triangle *> cand;
	GLdouble scalar_prod, mod1, mod2;
	for (vector<Triangle *>::iterator it = triangs.begin (); it != triangs.end (); it++)
		{	
			if ((*it) == t)
				continue;
			scalar_prod = (*it)->normalv ().x () * t->normalv ().x () + 
										(*it)->normalv ().y () * t->normalv ().y () + 
										(*it)->normalv ().z () * t->normalv ().z ();
			mod1 = sqrt (t->normalv ().x () * t->normalv ().x  () + 
									t->normalv ().y () * t->normalv ().y () +
									t->normalv ().z () * t->normalv ().z ());
			mod2 = sqrt ((*it)->normalv ().x () * (*it)->normalv ().x  () + 
									(*it)->normalv ().y () * (*it)->normalv ().y () +
									(*it)->normalv ().z () * (*it)->normalv ().z ());
			if (abs (scalar_prod) == abs (mod1 * mod2))
				cand.push_back (*it);
		}
	vector<Triangle *> face;
	face.push_back(t);
	
	/* For each triangle, check if it's next to 
   * the triangles that compound the face */
	int total_added = 1;
	bool added = false;

	while (total_added > 0)
	{
		total_added = 0;
		for (vector<Triangle *>::iterator it = cand.begin (); it != cand.end (); it++)
		{
			if (*it == NULL)
				continue;	
			for(vector<Triangle *>::iterator f = face.begin (); f!=face.end () && added == false; f++)
			{
				if((*it)->adyacent(*f))
				{
					face.push_back(*it);
					cand[it - cand.begin ()] = NULL;
					total_added++;	
					added = true;
				}
			}
		}	
	}
	return face;
}

vector<Triangle *> 
Mesh::get_triangs ()
{
	return triangs;
}

vector<Vertex3D *> 
Mesh::get_verts ()
{
	return verts;
}

void 
Mesh::add_vertex (Vertex3D *v)
{
	verts.push_back (v);
}

void
Mesh::add_triangle (Triangle *t)
{
	triangs.push_back (t);
}

Triangle *
Mesh::get_triangle (GLuint n)
{
	return triangs.at (n);
}
 
Vertex3D *
Mesh::get_vertex (GLuint n)
{
	return verts.at (n);
}
 
Vertex3D Mesh::get_com()
{
	return com;
}

void
Mesh :: set_state(TState s)
{
	state = s;
}

TState
Mesh :: get_state()
{
	return state;
}
